package com.example.springboot.utilabstract;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.util.http.fileupload.FileUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.*;

/**
 * @author fengyuan
 * @date 2019-03-11 15:47:22
 * @Description TODO 公用Java方法
 */
@Slf4j
public abstract class BasePubFun {

    /**
     * 获取移除横线并转大写的UUID
     */
    public static final String getUUID() {
        return UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
    }

    /**
     * 时间+随机数=流水号
     *
     * @return
     */
    public static String getSerial(String pre, Integer len) {
        Random rm = new Random();
        Integer pross = (int) ((1 + rm.nextDouble()) * Math.pow(10, len));
        String rand = String.valueOf(pross).substring(1, len + 1);
        return pre.toUpperCase() + BaseDate.getCurrDate("yyMMddHHmmssSSS") + rand;
    }

    /**
     * 时间戳+随机数=流水号
     */
    public static String getSerialSjc(String pre, Integer len) {
        Random rm = new Random();
        Integer pross = (int) ((1 + rm.nextDouble()) * Math.pow(10, len));
        String rand = String.valueOf(pross).substring(1, len + 1);
        return pre.toUpperCase() + System.currentTimeMillis() + rand;
    }


    /**
     * 校验Json
     */
    public static boolean chkJson(String jsonStr) {

        if (StringUtils.isBlank(jsonStr)) {
            return false;
        }
        try {
            @SuppressWarnings("unused")
            JSONObject jsonObject = JSONObject.parseObject(jsonStr);
        } catch (Exception e) {
            try {
                @SuppressWarnings("unused")
                JSONArray jsonArray = JSONObject.parseArray(jsonStr);
            } catch (Exception ex) {
                return false;
            }
        }
        return true;
    }

    /**
     * 将一级json转换为map
     */
    public static SortedMap<String, String> toHashMap(JSONObject jObject) {
        SortedMap<String, String> data = new TreeMap<>();
        // 遍历jsonObject数据，添加到Map对象
        for (String key : jObject.keySet()) {
            String value = jObject.getString(key);
            data.put(key, value);
        }
        return data;
    }

    /**
     * 获取本机的ip
     *
     * @param ipStartWith
     * @return
     */
    public static String getLocalIp(String ipStartWith) {
        try {
            Enumeration allNetInterfaces = NetworkInterface.getNetworkInterfaces();
            InetAddress ip;
            while (allNetInterfaces.hasMoreElements()) {
                NetworkInterface netInterface = (NetworkInterface) allNetInterfaces.nextElement();
                Enumeration addresses = netInterface.getInetAddresses();
                while (addresses.hasMoreElements()) {
                    ip = (InetAddress) addresses.nextElement();
                    if (ip != null && ip instanceof Inet4Address) {
                        String ipStr = ip.getHostAddress();
                        if (ipStr.startsWith(ipStartWith)) {
                            return ipStr;
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("获取本机ip异常![{}]", e.toString());
            return "";
        }
        return "";
    }

    public boolean getLocalIps(String ipStartWith) {
        try {
            Enumeration allNetInterfaces = NetworkInterface.getNetworkInterfaces();
            InetAddress ip;
            while (allNetInterfaces.hasMoreElements()) {
                NetworkInterface netInterface = (NetworkInterface) allNetInterfaces.nextElement();
                Enumeration addresses = netInterface.getInetAddresses();
                while (addresses.hasMoreElements()) {
                    ip = (InetAddress) addresses.nextElement();
                    if (ip != null && ip instanceof Inet4Address) {
                        String ipStr = ip.getHostAddress();
                        if (ipStr.startsWith(ipStartWith)) {
                            return true;
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("错误:[{}]", e.toString());
            return false;
        }
        return false;
    }


    /**
     * 获取本机ip地址，兼容linux本方法
     */
    public static String getLocalIp() {
        Enumeration allNetInterfaces;
        try {
            allNetInterfaces = NetworkInterface.getNetworkInterfaces();
            InetAddress ip;
            String ipAddress = "";
            while (allNetInterfaces.hasMoreElements()) {
                NetworkInterface netInterface = (NetworkInterface) allNetInterfaces.nextElement();
                log.debug("netInterface.getName:[{}]", netInterface.getName());
                Enumeration addresses = netInterface.getInetAddresses();
                while (addresses.hasMoreElements()) {
                    ip = (InetAddress) addresses.nextElement();
                    if (ip != null && ip instanceof Inet4Address) {
                        ipAddress = ip.getHostAddress();
                    }
                }
            }
            return ipAddress;
        } catch (SocketException e) {
            e.printStackTrace();
            return "获取本地Ip异常";
        }
    }

    /**
     * 获取客户端ip
     */
    public static String getRemoteHost(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (StringUtils.isNotBlank(ip) && !"unKnown".equalsIgnoreCase(ip)) {
            //多次反向代理后会有多个ip值，第一个ip才是真实ip
            int index = ip.indexOf(",");
            if (index != -1) {
                return ip.substring(0, index);
            } else {
                return ip;
            }
        }
        ip = request.getHeader("X-Real-IP");
        if (StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
            return ip;
        }
        return request.getRemoteAddr();
    }

    /**
     * 客户端使用nginx等反向代理发送请求的时候，获取的ip地址不是真实的  通过下面方法  获取真实地址
     */
    public static String getRemoteHost1(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-real-ip");
            if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader(" X-Real-IP");
                if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
                    ip = request.getHeader("Proxy-Client-IP");
                    if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
                        ip = request.getHeader("WL-Proxy-Client-IP");
                        if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
                            ip = request.getHeader("HTTP_CLIENT_IP");
                            if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
                                ip = request.getHeader("HTTP_X_FORWARDED_FOR");
                                if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
                                    ip = request.getRemoteAddr();
                                }
                            }
                        }
                    }
                }
            }
        } else if (ip.length() > 15) {
            String[] ips = ip.split(",");
            for (int index = 0; index < ips.length; index++) {
                String strIp = ips[index];
                if (!("unknown".equalsIgnoreCase(strIp))) {
                    ip = strIp;
                    break;
                }
            }
        }
        return ip;
    }

    public static String getRemoteMac(HttpServletRequest request) {
        String str;
        String macAddress = "";
        String ip = getRemoteHost(request);

        try {
            Process p = Runtime.getRuntime().exec("nbtstat -a " + ip);
            InputStreamReader ir = new InputStreamReader(p.getInputStream());
            LineNumberReader input = new LineNumberReader(ir);
            for (int i = 1; i < 100; ++i) {
                str = input.readLine();
                if (str != null && str.indexOf("MAC") > 1) {
                    macAddress = str.substring(str.indexOf("=") + 2, str.length());
                    break;
                }
            }
        } catch (IOException var8) {
            var8.printStackTrace(System.out);
        }

        return macAddress;
    }

    /**
     * 给对象的所有属性设置默认值
     */
    public static void setDefaultValForObj(Object obj) {
        try {
            // 获取实体类的所有属性并赋上默认值
            Class<?> clazz = obj.getClass();
            for (; clazz != Object.class; clazz = clazz.getSuperclass()) {//向上循环  遍历父类
                Field[] fields = clazz.getDeclaredFields();
                for (Field field : fields) {
                    field.setAccessible(true);
                    if (field.get(obj) != null) {
                        continue;
                    }
                    String type = field.getGenericType().toString();
                    // 如果type是类类型，则前面包含"class "，后面跟类名
                    if (type.equals("class java.lang.String")) {
                        field.set(obj, "");
                    } else if (type.equals("class java.lang.Integer")) {
                        field.set(obj, 0);
                    } else if (type.equals("class java.lang.Long")) {
                        field.set(obj, 0L);
                    } else if (type.equals("class java.math.BigDecimal")) {
                        field.set(obj, new BigDecimal(0));
                    } else if (type.equals("class java.lang.Double")) {
                        field.set(obj, 0);
                    } else if (type.equals("class java.lang.Boolean")) {
                        field.set(obj, false);
                    } else if (type.equals("class java.util.Date")) {
                        field.set(obj, new Date());
                    }

                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 拷贝源对象的属性的值到目标对象的同名属性
     */
    public static void setSourceValToTargetVal(Object source, Object target) {
        try {
            Field[] fieldSources = source.getClass().getDeclaredFields();
            for (Field field : fieldSources) {
                field.setAccessible(true);
                if (field.get(source) == null) {
                    continue;
                }

                Field f = target.getClass().getDeclaredField(field.getName());
                f.setAccessible(true);
                f.set(target, field.get(source));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 将传入的字符串转小写后在将首字母大写
     * 效率是最高的
     */
    private static String convertToCamel(String fildeName) {
        byte[] items = fildeName.toLowerCase().getBytes();
        items[0] = (byte) ((char) items[0] - 'a' + 'A');
        return new String(items);
    }

    /**
     * 获取根目录
     */
    public static String getRootPath() {
        //获取根目录
        String rootPath = System.getProperty("java.class.path");
        // rootPath = D:\aaaaaaaaa\climb-fts-webapi-0.0.1-SNAPSHOT-exec.jar
        int firstIndex = rootPath.lastIndexOf(System.getProperty("path.separator")) + 1;
        // firstIndex = 0
        int lastIndex = rootPath.lastIndexOf(File.separator) + 1;
        // lastIndex = 13
        rootPath = rootPath.substring(firstIndex, lastIndex);
        // rootPath = D:\aaaaaaaaa\
        return rootPath;
    }

    /**
     * 根据系统 返回RootPath+dirName的路径
     */
    public static String getPathByRoot(String dirName) {

        String rootPath = "";
        String path = getRootPath();
        if ("\\".equals(File.separator)) {
            // windows path
            rootPath = path.replace("/", "\\") + dirName + "\\";
        } else if ("/".equals(File.separator)) {
            // linux path
            rootPath = path.replace("\\", "/") + dirName + "/";
        }
        if (!createDir(rootPath)) {
            System.out.println("目录创建失败");
        }
        return rootPath;
    }

    /**
     * 创建目录
     */
    public static boolean createDir(String destDirName) {

        File dir = new File(destDirName);
        // 判断目录是否存在
        if (dir.exists()) {
            return true;
        }
        // 创建目标目录
        if (dir.mkdirs()) {
            return true;
        }
        System.out.println("目录创建失败：" + destDirName);
        return false;
    }

    /**
     * 删除文件及文件夹
     */
    public static void deleteFileOrDir(String filePath) {

        try {

            File file = new File(filePath);
            if (!file.exists()) {
                return;
            }

            FileUtils.forceDelete(file);
        } catch (Exception e) {
            log.error("异常[{}]", e.toString());
        }

    }

    /**
     * 异步删除文件及文件夹
     */
    @Async
    public static void deleteFileOrDirAsync(String filePath) {

        deleteFileOrDir(filePath);

    }

    /**
     * 文件转64位编码
     */
    public static String getFileToCode(MultipartFile file) {
        InputStream in;
        byte[] data = null;

        try {
            in = file.getInputStream();
            data = new byte[in.available()];
            in.read(data);
            in.close();
        } catch (IOException var4) {
            var4.printStackTrace();
        }
        return new String(org.apache.commons.codec.binary.Base64.encodeBase64(data));
    }

    // 读取流信息并返回
    public static String readInputStream(InputStream inputStream) throws IOException {
        StringBuilder sb = new StringBuilder();
        try (BufferedReader br = new BufferedReader(new InputStreamReader(inputStream))) {
            String line;
            while ((line = br.readLine()) != null) {
                sb.append(line).append("\n");
            }
        }
        return sb.toString();
    }

    public static String getRedisKey(String... str) {
        String rstStr = "";
        for (String temp : str) {
            rstStr += temp + ":";
        }
        return rstStr.substring(0, rstStr.length() - 1);
    }
}
